﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Drawing;
using System.Windows.Forms;
using System.IO;
using System.Collections;

namespace SplitMatch
{
    class Matching
    {
        private TextBox m_Result;
        private TextBox m_Time;
        private TextBox m_OriL;

        private TextBox m_picName;          // 生成图片的名字
        

        private PictureBox m_picBoxBase;    // Base的pictureBox
        private PictureBox m_picBoxMatch;   // Match的pictureBox
        private Button m_btnMatch;          

        private String m_Base;
        private String m_Match;

        private   Label m_AllMResult;
        private   string m_Log;
        private   string m_Dir;
        private   Button m_btnAllMatch;

        // 辅助变量
        FileStream m_pFileStream;


        // 用这个来停住生产者线程 并释放串口资源.
        private volatile bool _shouldStop;



        /// <summary>
        /// 单幅的构造函数
        /// </summary>
        /// <param name="tBOriL"></param>
        /// <param name="txtBResult"></param>
        /// <param name="tBTime"></param>
        /// <param name="picBoxBase"></param>
        /// <param name="btnSingleMatch"></param>
        /// <param name="strBase"></param>
        /// <param name="strMatch"></param>
        public Matching(
                        TextBox tBOriL,
                        TextBox txtBResult, 
                        TextBox tBTime, 
                        PictureBox picBoxBase, 
                        Button btnSingleMatch,
                        String strBase,
                        String strMatch)
        {
            // TODO: Complete member initialization
            this.m_OriL = tBOriL;
            this.m_Result = txtBResult;
            this.m_Time = tBTime;
            this.m_picBoxBase = picBoxBase;
            this.m_btnMatch = btnSingleMatch;

            m_Base = strBase;
            m_Match = strMatch;
        }

        /// <summary>
        /// 批处理的构造函数
        /// </summary>
        /// <param name="AllMResult"></param>
        /// <param name="strLog"></param>
        /// <param name="strDir"></param>
        /// <param name="picBoxBase"></param>
        /// <param name="btnAllMatch"></param>
        public Matching(Label AllMResult,
                        string strLog,
                        string strDir,
                        PictureBox picBoxBase,
            PictureBox pixBoxMatch,
            TextBox tOriL,
                        Button btnAllMatch)
        {
            // TODO: Complete member initialization
            m_AllMResult = AllMResult;
            m_Log = strLog;
            m_Dir = strDir;
            m_btnAllMatch = btnAllMatch;

            m_picBoxBase = picBoxBase;
            m_picBoxMatch = pixBoxMatch;
            this.m_OriL = tOriL;

            _shouldStop = false;
        }

        
        /// <summary>
        /// 用来做匹配copy的构造函数
        /// </summary>
        /// <param name="labelresult">显示结果Label</param>
        /// <param name="strBase">大图Size</param>
        /// <param name="strDir">目录路径</param>
        /// <param name="strLog">log名字位置</param>
        public Matching(Label labelresult, 
                        string strBase, 
                        string strDir, 
                        string strLog)
        {
            // TODO: Complete member initialization

            this.m_AllMResult = labelresult;
            this.m_Base = strBase;
            this.m_Dir = strDir;
            this.m_Log = strLog;
        }

        public Matching(Label labelresult, 
                        TextBox textPicName, 
                        string strBase, 
                        string strDir, 
                        string strLog)
        {
            // TODO: Complete member initialization
            this.m_AllMResult = labelresult;
            this.m_Base = strBase;
            this.m_Dir = strDir;
            this.m_Log = strLog;

            m_picName = textPicName;
        }

        /// <summary>
        /// 图变白底
        /// </summary>
        public void PicChangeWhite()
        {
            // 选择IR大图，生成
            Byte[,] bCsharp = HandleTIF.ReadTifFile(this.m_Base);


            // 选择suslog，遍历所有成功的图



            // 设定目录 获得小图目录
            String strDir = m_Dir;
            String[] filesPic = Directory.GetFiles(strDir);

            // 根据log文件，获取fal的所有项.
            List<String> strFiles = GetLogs(this.m_Log);

            // 选择小图序列，用于在IR图里设置为白色
            // 获取一个图片的模板
            String strModel = GetModel(filesPic[0]);
            String strEach = string.Empty;
            int nNum = strFiles.Count;
            for (int i = 0; i < nNum; i++)
            {

                String strEachLog = strFiles[i];

                // 设置处理进程.
                String strShowResult = String.Format("{0}/{1} {2}",
                                                        (i + 1).ToString(),
                                                        nNum.ToString(),
                                                        strEachLog);

                SetResultState(this.m_AllMResult, strShowResult);


                // 根据图片模板和log信息，组合出实际的成功小图路径.
                strEach = GetFinalFile(strModel, strEachLog);

                // 在IR图里设置为白色
                SetWhiteToBase(strEach, bCsharp);
                //SetSmallToBase(strEach, bCsharp);
            }


            // 设定完成的匹配标注图
            String strChecked = this.m_picName.Text;
            // 保存文件

            // 写文件
            HandleTIF.SaveTIFFile(bCsharp, strChecked);

            bCsharp = null;
        }

        /// <summary>
        /// 在大图里设置白图
        /// </summary>
        /// <param name="strEach"></param>
        /// <param name="bCsharp"></param>
        private void SetWhiteToBase(string strEach, byte[,] bCsharp)
        {
            // 获取小图矩阵
            byte[,] Smallpic = HandleTIF.ReadTifFile(strEach);

            // 获取位置. 
            Location eachL = GetLocation(strEach);

            Byte nWhite = 255;

            // 基准+偏移 = 小图原始位置
            int nRow = BasePicHandle.GetROW(Smallpic);
            int nCol = BasePicHandle.GetCOL(Smallpic);
            int nOffRow = 0;
            int nOffCol = 0;


            for (int i = 0; i < nRow; i++)
            {
                for (int j = 0; j < nCol; j++)
                {
                    nOffRow = i + eachL.row;
                    nOffCol = j + eachL.column;

                    bCsharp[nOffRow, nOffCol] = nWhite;
                }
            }
        }

        /// <summary>
        /// 白底贴图
        /// </summary>
        public void ThreadCheckCopy()
        {
            // 选择CCD大图，获取大小，生成一张白色底图
            Image tempImage = Image.FromFile(this.m_Base);
            int nCol = tempImage.Width;
            int nRow = tempImage.Height;
            tempImage.Dispose();

            Byte[,] bCsharp = new Byte[nRow, nCol];
            // 变成白色.
            for (int i = 0; i < nRow; i++)
            {
                for (int j = 0; j < nCol; j++)
                {
                    bCsharp[i, j] = 255;
                }
            }

            // 选择suslog，遍历所有成功的图


            // 设定目录 获得小图目录
            String strDir = m_Dir;
            String[] filesPic = Directory.GetFiles(strDir);

            // 根据log文件，获取sus的所有项.
            List<String> strFiles = GetLogs(this.m_Log);

            // 选择小图序列，用于copy到白色底图里
            // 获取一个图片的模板
            String strModel = GetModel(filesPic[0]);
            String strEach = string.Empty;
            int nNum = strFiles.Count;
            for (int i = 0; i < nNum; i++)
            {

                String strEachLog = strFiles[i];

                // 设置处理进程.
                String strShowResult = String.Format("{0}/{1} {2}",
                                                        (i + 1).ToString(),
                                                        nNum.ToString(),
                                                        strEachLog);

                SetResultState(this.m_AllMResult, strShowResult);

                
                // 根据图片模板和log信息，组合出实际的成功小图路径.
                strEach = GetFinalFile(strModel, strEachLog);

                // 用小图路径贴在白底的大图上
                SetSmallToBase(strEach, bCsharp);
            }


            // 设定完成的匹配标注图
            String strChecked = "Checked.tif";
            // 保存文件

            // 写文件
            HandleTIF.SaveTIFFile(bCsharp, strChecked);

            bCsharp = null;


        }

        /// <summary>
        /// 把所有的小图贴在Base图上
        /// </summary>
        /// <param name="strEach"></param>
        /// <param name="bCsharp"></param>
        private void SetSmallToBase(string strEach, byte[,] bCsharp)
        {
            // 获取小图矩阵
            byte[,] Smallpic = HandleTIF.ReadTifFile(strEach);

            // 获取位置. 
            Location eachL = GetLocation(strEach);


            // 基准+偏移 = 小图原始位置
            int nRow = BasePicHandle.GetROW(Smallpic);
            int nCol = BasePicHandle.GetCOL(Smallpic);
            int nOffRow = 0;
            int nOffCol = 0;


            for (int i = 0; i < nRow; i++)
            {
                for (int j = 0; j < nCol; j++)
                {
                    nOffRow = i + eachL.row;
                    nOffCol = j + eachL.column;

                    bCsharp[nOffRow, nOffCol] = Smallpic[i, j];
                }
            }
            
        }

        /// <summary>
        /// 从文件名字获取位置
        /// </summary>
        /// <param name="strEach"></param>
        /// <returns></returns>
        private Location GetLocation(string strEach)
        {
            Location lRtn = new Location();

            String[] strParts = strEach.Split('.');
            String strFile = strParts[0];


            strParts = strFile.Split('\\');
            String strSingleFile = strParts[strParts.Length - 1];

            strParts = strSingleFile.Split('_');

            // 记录一下 ir_256_256_0_0

            // Row = 3
            int nRow = strParts.Length - 2;
            String strRow = strParts[nRow];
            // Col = 4
            int nCol = strParts.Length - 1;
            String strCol = strParts[nCol];


            lRtn.row = Convert.ToInt32(strRow);
            lRtn.column = Convert.ToInt32(strCol);


            return lRtn;
        }

        /// <summary>
        /// 获取txt里完整的所有记录
        /// </summary>
        /// <param name="p"></param>
        /// <returns></returns>
        private List<string> GetLogs(string strLog)
        {
            List<string> strList = new List<string>();

            StreamReader sr = new StreamReader(strLog);

            String line;
            // Read and display lines from the file until the end of 
            // the file is reached.
            while ((line = sr.ReadLine()) != null)
            {
                // 切断line 提取需要的资源.
                strList.Add(line);
            }

            sr.Close();
            sr.Dispose();


            return strList;
        }

        /// <summary>
        /// 组合图片
        /// </summary>
        /// <param name="strModel"></param>
        /// <param name="strEachLog"></param>
        /// <returns></returns>
        private string GetFinalFile(string strModel, string strEachLog)
        {
            String strRtn = String.Empty;

            String[] parts = strEachLog.Split(' ');
            String strLocation = parts[0];

            String[] strLocations = strLocation.Split(',');

            strRtn = String.Format("{0}{1}_{2}.tif", 
                                    strModel, 
                                    strLocations[0], 
                                    strLocations[1]);


            return strRtn;
        }

        /// <summary>
        /// 返回模板名字
        /// </summary>
        /// <param name="strPic"></param>
        /// <returns></returns>
        private string GetModel(string strPic)
        {
            String strRtn = String.Empty;

            // C:\Users\YL\Desktop\0813Update\IR_Report\IR_256_256_20\Pic\ir_256_256_0_0.tif

            // 保留C:\Users\YL\Desktop\0813Update\IR_Report\IR_256_256_20\Pic\ir_256_256_

            int nNum = strPic.Length;

            strRtn = strPic.Remove(nNum - 7);



            return strRtn;
        }

        /// <summary>
        /// 多线程匹配
        /// 输入一个大图和小图， 直接写界面 匹配位置 匹配结果和 显示图片
        /// 归一化方法
        /// </summary>
        public void ThreadMatch2()
        {
            // 把按钮设置为不可用. 设置安全访问函数
            SetBtnState(m_btnMatch, false, "正在匹配");

            // 设置原图的位置.
            String strOriL = GetOriL(m_Match);
            SetTxTState(m_OriL, strOriL);

            // 记录一个开始时间
            Int32 nStart = GetTime();
            Location l = Match2(m_Base, m_Match);
            String strShowResult = String.Format("{0},{1}", l.row, l.column);

            // 设置匹配地址
            SetTxTState(m_Result, strShowResult);

            Int32 nEnd = GetTime();

            // 找到最佳点并显示
            FindLShow(l, m_Base, m_Match, m_picBoxBase);

            // 设置匹配时间
            Int32 nTimeOff = Math.Abs(nEnd - nStart);
            Decimal dShow = nTimeOff / 1000.0m;
            SetTxTState(m_Time, dShow.ToString());

            // 匹配完成 把按钮设置为可用.
            SetBtnState(m_btnMatch, true, "单图匹配");

            Console.WriteLine();
        }

        /// <summary>
        /// 多线程匹配
        /// 输入一个大图和小图， 直接写界面 匹配位置 匹配结果和 显示图片
        /// </summary>
        /// <param name="strBase"></param>
        /// <param name="strMatch"></param>
        public void ThreadMatch1()
        {
            // 把按钮设置为不可用. 设置安全访问函数
            SetBtnState(m_btnMatch, false, "正在匹配");

            // 设置原图的位置.
            String strOriL = GetOriL(m_Match);
            SetTxTState(m_OriL, strOriL);
                    
            // 记录一个开始时间
            Int32 nStart = GetTime();
            Location l = Match1(m_Base, m_Match);
            String strShowResult = String.Format("{0},{1}", l.row, l.column);

            // 设置匹配地址
            SetTxTState(m_Result, strShowResult);

            Int32 nEnd = GetTime();

            // 找到最佳点并显示
            FindLShow(l, m_Base, m_Match, m_picBoxBase);

            // 设置匹配时间
            Int32 nTimeOff = Math.Abs(nEnd - nStart);
            Decimal dShow = nTimeOff / 1000.0m;
            SetTxTState(m_Time, dShow.ToString());

            // 匹配完成 把按钮设置为可用.
            SetBtnState(m_btnMatch, true, "单图匹配");

            Console.WriteLine();
        }

        /// <summary>
        /// 根据名字获得坐标
        /// </summary>
        /// <param name="m_Match"></param>
        /// <returns></returns>
        private string GetOriL(string m_Match)
        {
            // ir_200_200_340_660.tif
            String strRtn = String.Empty;

            String[] parts = m_Match.Split('.');
            String strName = parts[0];
            parts = strName.Split('_');
            int nNum = parts.Length;

            // nNum - 2 = 340   nNum - 1 = 660
            strRtn = String.Format("{0},{1}", parts[nNum - 2], parts[nNum - 1]);

            return strRtn;
        }

        /// <summary>
        /// 在线程里处理循环匹配
        /// </summary>
        public void ThreadAllMatch()
        {
            // 把按钮设置为不可用. 设置安全访问函数
            SetBtnState(this.m_btnAllMatch, false, "正在匹配");


            // 读取Log记录
            List<String> logFiles = GetRecord(m_Log);

            // 设定目录
            String strDir = m_Dir;
            String[] files = Directory.GetFiles(strDir);

            
            // 大图位置.
            String strBaseName = m_picBoxBase.Tag.ToString();


            // 循环遍历文件
            int nFilesNum = files.Length;
            for (int i = 0; i < nFilesNum; i++)
            {
                // 从外部控制线程停止
                if (true == _shouldStop)
                {
                    break;
                }

                // 获取单个文件名字
                String strEach = files[i];

                // 设置处理进程.
                String strShowResult = String.Format("{0}/{1} {2}",
                                                        (i+1).ToString(),
                                                        nFilesNum.ToString(),
                                                        strEach);

                SetResultState(this.m_AllMResult, strShowResult);


                // 设置小图
                SetPicture(this.m_picBoxMatch, strEach);



                // 提取文件的Row和Col组合
                String fileLocation = GetLocationForm(strEach);

                // 设置文件原位置.
                SetTxTState(m_OriL, fileLocation);


                // 并和log里的记录比较
                // 如果已经存在记录，则不作匹配，并把文件删除
                bool bIsHandle = CheckIfHandled(fileLocation, logFiles);

                if (true != bIsHandle)
                {
                    // 创建对象Matching
                    //Matching mEach = new Matching();
                    Location eachMatchLocation = Match1(strBaseName, strEach);

                    // 分别组合文件坐标和匹配坐标为string.
                    String matchLocation = String.Format("{0},{1}",
                                                        eachMatchLocation.row,
                                                        eachMatchLocation.column);

                    String eachLog = String.Format("{0} {1}",
                                                    fileLocation,
                                                    matchLocation);

                    // 写入一个记录文件中
                    WriteLog(eachLog, this.m_Log);

                }
                else
                {
                    // 略过处理，只是最后把小图删除
                }


                // 把pictureMatch释放掉.
                DisposePic(this.m_picBoxMatch);

                // 处理完一个小图后，把文件删除
                File.Delete(strEach);
                //Console.WriteLine();

                // 强制回收内存.
                System.GC.Collect();

            } // for 循环


            // 如果不是强制退出，重新设置界面
            if (true != _shouldStop)
            {
                SetBtnState(this.m_btnAllMatch, true, "批量匹配");
            }
        }

        /// <summary>
        /// 释放掉pictureBox
        /// </summary>
        /// <param name="pBox"></param>
        private void DisposePic(PictureBox pBox)
        {
            pBox.Invoke(
            new MethodInvoker(
            delegate
            {

                // 释放文件资源.
                m_pFileStream.Close();
                m_pFileStream.Dispose();

                // 组合状态.
                // pBox.Dispose();
            }
            )
            );
        }

        /// <summary>
        /// 设置匹配小图
        /// </summary>
        /// <param name="pictureBox"></param>
        /// <param name="strEach"></param>
        private void SetPicture(PictureBox pBox, string strFile)
        {
            pBox.Invoke(
            new MethodInvoker(
            delegate
            {
                // 组合状态.
                //pictureBox.Image = Image.FromFile(strEach);


                // 通过流的方式 保存文件,不用把文件锁住.
                m_pFileStream = new FileStream(strFile, FileMode.Open, FileAccess.Read);
                pBox.Image = Image.FromStream(m_pFileStream);


                //// 释放文件资源.
                //pFileStream.Close();
                //pFileStream.Dispose();

            }
            )
            );
        }

        private void SetResultState(Label label, string strShowResult)
        {
            label.Invoke(
            new MethodInvoker(
            delegate
            {
                // 组合状态.
                label.Text = strShowResult;
            }
            )
            );
        }

        /// <summary>
        /// 写一条记录
        /// </summary>
        /// <param name="strLog"></param>
        /// <param name="fileName"></param>
        private void WriteLog(string strLog, string fileName)
        {
            FileStream fs = new FileStream(fileName, FileMode.Append);
            StreamWriter sw = new StreamWriter(fs);
            //开始写入
            sw.WriteLine(strLog);


            //清空缓冲区
            sw.Flush();
            //关闭流
            sw.Close();
            fs.Close();
        }

        /// <summary>
        /// 查找是否在文件里
        /// </summary>
        /// <param name="fileLocation"></param>
        /// <param name="logFiles"></param>
        /// <returns></returns>
        private bool CheckIfHandled(string fileLocation, List<string> logFiles)
        {
            bool bRtn = false;

            bool bContains = logFiles.Contains(fileLocation);

            // 如果存在文件，则认为处理过.
            bRtn = bContains;

            return bRtn;
        }

        /// <summary>
        /// 从Log文件形成项
        /// </summary>
        /// <param name="strEach"></param>
        /// <returns></returns>
        private string GetLocationForm(string strEach)
        {
            String[] parts = strEach.Split('\\');


            // 用_获取 row 和 col
            String fileName = parts[parts.Length - 1];
            String[] withOutparts = fileName.Split('.');
            fileName = withOutparts[0];

            String[] Smallparts = fileName.Split('_');


            String fileLocation = String.Format("{0},{1}",
                                                Smallparts[3],
                                                Smallparts[4]);
            return fileLocation;
        }

        /// <summary>
        /// 根据Log文件，获取所有项
        /// </summary>
        /// <param name="strLog"></param>
        /// <returns></returns>
        private List<string> GetRecord(string strLog)
        {
            List<string> strList = new List<string>();

            StreamReader sr = new StreamReader(strLog);

            String line;
            // Read and display lines from the file until the end of 
            // the file is reached.
            while ((line = sr.ReadLine()) != null)
            {
                // 切断line 提取需要的资源.
                String[] parts = line.Split(' ');
                strList.Add(parts[0]);
            }

            sr.Close();
            sr.Dispose();


            return strList;
        }

        /// <summary>
        /// 线程设置结果
        /// </summary>
        /// <param name="m_Result"></param>
        /// <param name="strShowResult"></param>
        private void SetTxTState(TextBox m_Result, string strShowResult)
        {
            m_Result.Invoke(
            new MethodInvoker(
            delegate
            {
                // 组合状态.
                m_Result.Text = strShowResult;
            }   

            )
            );
        }

        private void SetBtnState(Button m_btnMatch, bool bEnable, string strShow)
        {
            m_btnMatch.Invoke(
            new MethodInvoker(
            delegate
            {
                // 组合状态.
                m_btnMatch.Text = strShow;
                m_btnMatch.Enabled = bEnable;
            }

            )
            );
        }


        private void FindLShow( Location bestLocation, 
                                string strBase, 
                                string strMatch, 
                                PictureBox picBox)
        {
            // 这里26*26就是图像可以匹配的位置, 当值最大时就是最佳匹配
            // FindLocation函数 找到最大值的位置并返回
            // 这个值代表匹配子图在基准图中的偏移量
            // 通过偏移量和匹配子图大小可以在基准图中找到最佳的匹配点


            // 这个MatrixG的意义是
            // 在这个矩阵里，有这么多个位置，返回了一个匹配度最好的值
            // 这个位置在这个矩阵里的偏移量，就认为是小图在大图里的偏移量

            String strSetName = String.Empty;

            String strFileName = strBase;
            // 如果是tif 用原有逻辑
            // 如果是其他图片，用新类型
            // 判断是不是tif结尾的.
            String[] parts = strFileName.Split('.');
            String strHou = parts[1];

            if ((strHou == "tif") || (strHou == "TIF"))
            {
                // 执行tif原型
                byte[,] Basepic = HandleTIF.ReadTifFile(strFileName);


                // 用偏移量和子图大小去改变基准图的元素，并显示基准图.
                // 获得picturebox 显示图片文件名字
                // 小图的Size也需要传进去.


                // 用bestLocation和MatrixG 算出偏移百分比
                // 用小图和大图算出 这个小图在这个大图里可以偏移的总量
                // 偏移总量 * 偏移百分比 = 需要标注的坐标点
                // 从这个点画一个小图大小的白框

                // Basepic : 大图矩阵
                // MatchPic: 小图矩阵
                // bestLocation: MatrixG中的最大值坐标点
                // MatrixG： 匹配矩阵


                // 拆分功能.
                // 1 返回一个匹配的坐标
                // 2 画图

                Location getLocation = bestLocation;

                //// 导出结果.
                //String strResult = string.Format("{0},{1}", getLocation.row, getLocation.column);
                //txtBResult.Text = strResult;

                // 在图片上画出白框
                byte[,] MatchPic = HandleTIF.ReadTifFile(strMatch);

                HandleTIF.DrawRetangle(Basepic, MatchPic, getLocation);


                strSetName = "Changed.tif";



                // 在对这个文件操作之前，要从picbox里把这个文件卸载了



                HandleTIF.SaveTIFFile(Basepic, strSetName);
            }
            else
            {
                //// 执行jpg原型，需要对RGB3个部分进行设置.

                //// 用一个新的image对象，把文件读取进来后，看看能不能保存成新的文件，或者直接替换

                //Image tempImage = Image.FromFile(strFileName);
                //mySize OriginSize = new mySize(0, 0);
                //OriginSize.COL = tempImage.Width;
                //OriginSize.ROW = tempImage.Height;

                //// 换算出精确坐标
                //Location getLocation = BasePicHandle.GetLocation(OriginSize,
                //                                                 MatchPic,
                //                                                bestLocation,
                //                                                MatrixG);

                //// 导出结果.
                //String strResult = string.Format("{0},{1}", getLocation.row, getLocation.column);
                //txtBResult.Text = strResult;

                //// 对图片 对tempImage进行改变 并保存
                //BasePicHandle.DrawRetangle(tempImage, MatchPic, getLocation);

                //strSetName = "Changed.tif";

                //// 保存图片 看看原图片有没有被改变
                //tempImage.Save(strSetName);

            }

            // 通过流的方式 保存文件,不用把文件锁住.
            FileStream pFileStream = new FileStream(strSetName, FileMode.Open, FileAccess.Read);

            picBox.Invoke(
            new MethodInvoker(
            delegate
            {
                // 组合状态.
                picBox.Image = Image.FromStream(pFileStream);
            }

            )
            );

            // 释放文件资源.
            pFileStream.Close();
            pFileStream.Dispose();
        }

        /// <summary>
        /// 非多线程匹配
        /// 输入一个大图和小图， 返回小图在大图里的匹配位置坐标.
        /// </summary>
        /// <param name="strBase"></param>
        /// <param name="strMatch"></param>
        /// <returns></returns>
        public Location Match2(String strBase, String strMatch)
        {
            Location lRtn = new Location();


            // 读取图片 在外层来分配内存 便于释放.

            // 用image库 可以知道需要分配的内存大小.

            mySize BaseSize = GetPicSize(strBase);
            double[,] PicBase = new double[BaseSize.ROW, BaseSize.COL];

            mySize matchSize = GetPicSize(strMatch);
            double[,] PicMatch = new double[matchSize.ROW, matchSize.COL];

            // 把图片数字设置到分配的内存里

            SetPicData(strBase, PicBase);
            SetPicData(strMatch, PicMatch);

            // 水平
            int nHorizontal = BaseSize.COL - matchSize.COL + 1;
            // 垂直
            int nVertical = BaseSize.ROW - matchSize.ROW + 1;

            // 建立临时的矩阵块
            double[,] tempM = new double[matchSize.ROW, matchSize.COL];

            Hashtable ht = new Hashtable();

            for (int i = 0; i < nHorizontal; i++)
            {
                for (int j = 0; j < nVertical; j++)
                {
                    
                    // 每次取出一个矩阵 来和小矩阵进行对比
                    SetMatrix(tempM, PicBase, i, j);

                    Location lTemp = new Location(i, j);

                    // 记录坐标和对比结果

                    double dEachResult = Match2Compare(tempM, PicMatch);

                    // hash表
                    ht.Add(lTemp, dEachResult);


                }
            }


            // 在hash表里找出最大的值. 返回Location.

            lRtn = GetLocation(ht);



            // 释放占用的内存.
            tempM = null;
            PicBase = null; // 设置为null 便于垃圾回收自动回收
            PicMatch = null; // 设置为null 便于垃圾回收自动回收

            return lRtn;
        }

        /// <summary>
        /// 在Hash表里找出最大的值，返回Location.
        /// </summary>
        /// <param name="ht"></param>
        /// <returns></returns>
        private Location GetLocation(Hashtable ht)
        {
            Location lRtn = new Location();
            // 找到最大的值.
            int nNum = ht.Count;
            double dMax = 0.0;

            foreach (DictionaryEntry  de in ht)
            {
                double dvalue = Convert.ToDouble(de.Value);
                if (dvalue > dMax)
                {
                    dMax = dvalue;
                }               
            }

            


            // 返回位置.
            foreach (DictionaryEntry de in ht)
            {
                double dvalue = Convert.ToDouble(de.Value);
                if (dMax == dvalue)
                {
                    lRtn = (Location)de.Key;
                    break;
                }
            }



            return lRtn;
        }

        /// <summary>
        /// 归一化方法 两个矩阵对比得值
        /// </summary>
        /// <param name="tempM">S</param>
        /// <param name="PicMatch">r</param>
        /// <returns></returns>
        private double Match2Compare(double[,] matrixS, double[,] matrixR)
        {
            //
            double dRtn = 0.0;

            // 矩阵求平均值.
            double dMeanS = BasePicHandle.MatrixMean(matrixS);
            double dMeanR = BasePicHandle.MatrixMean(matrixR);

            int nRow = BasePicHandle.GetROW(matrixR);
            int nCol = BasePicHandle.GetCOL(matrixR);


            // 

            double dsOff = 0.0;
            double drOff = 0.0;
            double dFenzi = 0.0;
            double dFenziTemp = 0.0;

            double dsPingFang = 0.0;
            double drPingFang = 0.0;
            double dFront = 0.0;
            double dBack = 0.0;

            for (int i = 0; i < nRow; i++)
            {
                for (int j = 0; j < nCol; j++)
                {
                    dsOff = matrixS[i, j] - dMeanS;
                    drOff = matrixR[i, j] - dMeanR;
                    dFenziTemp = dsOff * drOff;
                    dFenzi = dFenzi + dFenziTemp;


                    dsPingFang = dsOff * dsOff;
                    dFront = dFront + dsPingFang;

                    drPingFang = drOff * drOff;
                    dBack = dBack + drPingFang;
                }
            }



            // 分母
            double dFenmu = Math.Sqrt(dFront * dBack);


            dRtn = dFenzi / dFenmu;


            return dRtn;
        }

        /// <summary>
        /// 根据位置从source中拷贝数据到destination
        /// </summary>
        /// <param name="tempM">destination</param>
        /// <param name="PicBase">source</param>
        /// <param name="offX">水平位置</param>
        /// <param name="offY">垂直位置</param>
        private void SetMatrix(double[,] tempM, double[,] PicBase, int offX, int offY)
        {
            int nRow = BasePicHandle.GetROW(tempM);
            int nCol = BasePicHandle.GetCOL(tempM);

            for (int i = 0; i < nRow; i++)
            {
                for (int j = 0; j < nCol; j++)
                {
                    tempM[i, j] = PicBase[i + offX, j + offY];
                }
            }
        }

        /// <summary>
        /// 非多线程匹配
        /// 输入一个大图和小图， 返回小图在大图里的匹配位置坐标.
        /// </summary>
        /// <param name="strBase"></param>
        /// <param name="strMatch"></param>
        /// <returns></returns>
        public Location Match1(String strBase, String strMatch)
        {
            Location lRtn = new Location();


            // 读取图片 在外层来分配内存 便于释放.

            // 用image库 可以知道需要分配的内存大小.

            mySize BaseSize = GetPicSize(strBase);
            double[,] PicBase = new double[BaseSize.ROW, BaseSize.COL];

            mySize matchSize = GetPicSize(strMatch);
            double[,] PicMatch = new double[matchSize.ROW, matchSize.COL];

            // 把图片数字设置到分配的内存里

            SetPicData(strBase, PicBase);
            SetPicData(strMatch, PicMatch);


            // 分割矩阵
            mySize baseSmallSize = new mySize(8, 8);
            // 既然有实时分配的情况 考虑只要取得了地址 就可以设置为null
            // 用来释放内存 循环释放Matrix这个二维矩阵的，再释放最外面的
            Matrix[,] MyBaseM = SplitMatrix(PicBase, baseSmallSize);
            Matrix[,] MyMatrixS = SplitMatrix(PicMatch, baseSmallSize);



            // 12个偏移量 为了求得新矩阵
            // 可以作为一个常量 放到另一个CS文件里
            Location[] Lvector = new Location[12];

            Lvector[0].row = -2;
            Lvector[0].column = -2;

            Lvector[1].row = -2;
            Lvector[1].column = -1;

            Lvector[2].row = -2;
            Lvector[2].column = 0;

            Lvector[3].row = -2;
            Lvector[3].column = 1;

            Lvector[4].row = -2;
            Lvector[4].column = 2;

            Lvector[5].row = -1;
            Lvector[5].column = -2;

            Lvector[6].row = -1;
            Lvector[6].column = -1;

            Lvector[7].row = -1;
            Lvector[7].column = 0;

            Lvector[8].row = -1;
            Lvector[8].column = 1;

            Lvector[9].row = -1;
            Lvector[9].column = 2;

            Lvector[10].row = 0;
            Lvector[10].column = -2;

            Lvector[11].row = 0;
            Lvector[11].column = -1;



            // 输入一个嵌套矩阵，输出一个List Matrix集合
            // 获得返回的List 通过这个值来释放内存
            List<Matrix> MBiglist = GetMatrixList(MyBaseM, Lvector);
            List<Matrix> MSmalist = GetMatrixList(MyMatrixS, Lvector);


            // 输入2个Matrix List， 输出整合好12通道数据的
            // 匹配矩阵
            Matrix MatrixG = PiPeiMatrix(MBiglist, MSmalist, Lvector);


            // 找到匹配位置并返回.


            // 这里26*26就是图像可以匹配的位置, 当值最大时就是最佳匹配
            // FindLocation函数 找到最大值的位置并返回
            // 这个值代表匹配子图在基准图中的偏移量
            // 通过偏移量和匹配子图大小可以在基准图中找到最佳的匹配点


            // 这个MatrixG的意义是
            // 在这个矩阵里，有这么多个位置，返回了一个匹配度最好的值
            // 这个位置在这个矩阵里的偏移量，就认为是小图在大图里的偏移量

            // 矩阵匹配位置
            Location bestLocation = FindLocation(MatrixG);


            // 计算出小图在大图中的匹配位置

            // 算出大图和小图的ROW和COL
            double dOffRow;
            double dOffCol;
            // 偏移百分比，如果是0， 则返回0.01.
            if (0 == bestLocation.row)
            {
                dOffRow = 0.01;
            }
            else
            {
                dOffRow = Convert.ToDouble(bestLocation.row) / MatrixG.Row;
            }

            if (0 == bestLocation.column)
            {
                dOffCol = 0.01;
            }
            else
            {
                dOffCol = Convert.ToDouble(bestLocation.column) / MatrixG.Column;
            }


            // 算出偏移总量
            int nOffRowSum = GetROW(PicBase) - GetROW(PicMatch);
            int nOffColSum = GetCOL(PicBase) - GetCOL(PicMatch);


            // 算出需要标注的坐标点  =  偏移总量 * 偏移百分比

            int nLRow = Convert.ToInt32(Math.Floor(dOffRow * nOffRowSum));
            int nLCol = Convert.ToInt32(Math.Floor(dOffCol * nOffColSum));

            lRtn.row = nLRow;
            lRtn.column = nLCol;



            // 释放占用的内存.

            myMatrixRelease(MBiglist);
            myMatrixRelease(MSmalist);
            MBiglist = null;
            MSmalist = null;

            myMatrixRelease(MyBaseM);
            myMatrixRelease(MyMatrixS);
            MyBaseM = null;
            MyMatrixS = null;

            Lvector = null;

            PicBase = null; // 设置为null 便于垃圾回收自动回收
            PicMatch = null; // 设置为null 便于垃圾回收自动回收

            return lRtn;
        }

        /// <summary>
        /// 返回COL 定义1就是COL
        /// </summary>
        /// <param name="PicBase"></param>
        /// <returns></returns>
        private int GetCOL(double[,] matrix)
        {
            return matrix.GetLength(1);
        }

        /// <summary>
        /// 返回ROW 定义0就是ROW
        /// </summary>
        /// <param name="matrix"></param>
        /// <returns></returns>
        private int GetROW(double[,] matrix)
        {
            return matrix.GetLength(0);
        }

        /// <summary>
        /// 返回矩阵中匹配位置
        /// </summary>
        /// <param name="MatrixG"></param>
        /// <returns></returns>
        private Location FindLocation(Matrix MatrixG)
        {
            Location lRtn = new Location(0, 0);

            // 先找最大值
            double dMax = FindMax(MatrixG);

            for (int i = 0; i < MatrixG.Row; i++)
            {
                for (int j = 0; j < MatrixG.Column; j++)
                {
                    double dValue = MatrixG.data[i, j];
                    if (dMax == dValue)
                    {
                        lRtn.row = i;
                        lRtn.column = j;
                        return lRtn;
                    }
                }
            }

            return lRtn;
        }

        /// <summary>
        /// 得到一个匹配矩阵，从里面找最大值
        /// </summary>
        /// <param name="MBiglist"></param>
        /// <param name="MSmalist"></param>
        /// <param name="Lvector"></param>
        /// <returns></returns>
        private Matrix PiPeiMatrix(List<Matrix> MBiglist, List<Matrix> MSmalist, Location[] Lvector)
        {
            // MBiglist * * 12
            // MSmalist * * 12
            // MFinallist * * 12

            int nVector = Lvector.Length;

            // 小图在大图上做移动匹配
            List<Matrix> MFinallist = new List<Matrix>();

            double dE = 0.0;

            for (int z = 0; z < nVector; z++)
            {
                //mylist[i].name
                Matrix MBig = MBiglist[z];
                Matrix MSmall = MSmalist[z];

                ABSMatrix(MBig);
                ABSMatrix(MSmall);

                // 输入2个矩阵，导出一个矩阵.         
                Matrix Mfinal = PiPei(MSmall, MBig);
                ABSMatrix(Mfinal);


                // 从Mfinal中找个最大值和第二大值
                double dMax = FindMax(Mfinal);
                double dSecondMax = FindSecondMax(Mfinal);

                // 算出主峰与次峰比值
                double dBiZhi = dMax / dSecondMax;

                // 得出一个新矩阵
                MatrixMulti(Mfinal, dBiZhi);

                // 记录新矩阵
                MFinallist.Add(Mfinal);

                // 记录主次峰比值

                dE = dE + dBiZhi;

            }
            // dE 之后会用到

            nVector = MFinallist.Count;

            // GetPiPeiSize
            mySize PiPeiSize = GetPiPeiSize(MBiglist[0], MSmalist[0]);

            Matrix MaxtrixSum = new Matrix(PiPeiSize.ROW, PiPeiSize.COL);
            for (int i = 1; i < nVector; i++)
            {
                Matrix eachM = MFinallist[i];

                // 求和
                MaxtrixAdd(MaxtrixSum, eachM);

            }


            // 矩阵除法
            Matrix MatrixG = MaxtrixDiv(MaxtrixSum, dE);


            // 释放资源.
            // 申请的临时变量 地址无法传递回上层函数
            myMatrixRelease(MFinallist);

            return MatrixG;
        }

        /// <summary>
        ///  矩阵除法
        /// </summary>
        /// <param name="MaxtrixSum"></param>
        /// <param name="dE"></param>
        /// <returns></returns>
        private Matrix MaxtrixDiv(Matrix MaxtrixSum, double dE)
        {
            if (0.0 == dE)
            {
                return null;
            }

            Matrix Mrtn = new Matrix(MaxtrixSum.Row, MaxtrixSum.Column);

            for (int i = 0; i < Mrtn.Row; i++)
            {
                for (int j = 0; j < Mrtn.Column; j++)
                {
                    Mrtn.data[i, j] = MaxtrixSum.data[i, j] / dE;
                }
            }

            return Mrtn;
        }

        /// <summary>
        /// 矩阵加法
        /// </summary>
        /// <param name="MaxtrixSum"></param>
        /// <param name="eachM"></param>
        private void MaxtrixAdd(Matrix MaxtrixSum, Matrix eachM)
        {
            for (int i = 0; i < MaxtrixSum.Row; i++)
            {
                for (int j = 0; j < MaxtrixSum.Column; j++)
                {
                    MaxtrixSum.data[i, j] = MaxtrixSum.data[i, j] + eachM.data[i, j];
                }
            }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="MBig"></param>
        /// <param name="MSmall"></param>
        /// <returns></returns>
        private mySize GetPiPeiSize(Matrix MBig, Matrix MSmall)
        {
            int iNewRow = MBig.Row - MSmall.Row + 1;
            int iNewCol = MBig.Column - MSmall.Column + 1;

            mySize sizeRtn = new mySize(iNewRow, iNewCol);


            return sizeRtn;
        }

        /// <summary>
        /// 矩阵乘法
        /// </summary>
        /// <param name="Mfinal"></param>
        /// <param name="dBiZhi"></param>
        private void MatrixMulti(Matrix Mfinal, double dBiZhi)
        {
            for (int i = 0; i < Mfinal.Row; i++)
            {
                for (int j = 0; j < Mfinal.Column; j++)
                {
                    Mfinal.data[i, j] = Mfinal.data[i, j] * dBiZhi;
                }
            }
        }

        /// <summary>
        /// 找到第二大值
        /// </summary>
        /// <param name="Mfinal"></param>
        /// <returns></returns>
        private double FindSecondMax(Matrix Mfinal)
        {
            double dSecondMax = 0.0;
            double dMax = FindMax(Mfinal);

            for (int i = 0; i < Mfinal.Row; i++)
            {
                for (int j = 0; j < Mfinal.Column; j++)
                {
                    double dCur = Mfinal.data[i, j];

                    if (dCur == dMax)
                    {
                        continue;
                    }
                    if (dCur > dSecondMax)
                    {
                        dSecondMax = dCur;
                    }
                }
            }

            return dSecondMax;
        }

        /// <summary>
        /// Find Max value.
        /// </summary>
        /// <param name="Mfinal"></param>
        /// <returns></returns>
        private double FindMax(Matrix Mfinal)
        {
                    
            double dMax = 0.0;

            for (int i = 0; i < Mfinal.Row; i++)
            {
                for (int j = 0; j < Mfinal.Column; j++)
                {
                    double dCur = Mfinal.data[i, j];
                    if (dCur > dMax)
                    {
                        dMax = dCur;
                    }
                }
            }

            return dMax;
        }

        /// <summary>
        /// 返回一个参考矩阵.
        /// </summary>
        /// <param name="MSmall"></param>
        /// <param name="MBig"></param>
        /// <returns></returns>
        private Matrix PiPei(Matrix MSmall, Matrix MBig)
        {
            // 算出新的匹配矩阵的大小
            // 小矩阵在大的矩阵上移动
            int iNewRow = MBig.Row - MSmall.Row + 1;
            int iNewCol = MBig.Column - MSmall.Column + 1;
            Matrix Mrtn = new Matrix(iNewRow, iNewCol);

            int iSmallRow = MSmall.Row;
            int iSmallCol = MSmall.Column;
            int offsetValue = 1;


            // 偏移指针
            Location baseL = new Location(0, 0);
            mySize size = new mySize(iSmallRow, iSmallCol); // 小匹配图大小

            for (int i = 0; i < iNewRow; i++)
            {

                // Big bug
                // i没有做偏移.
                baseL.row = i * offsetValue;

                for (int j = 0; j < iNewCol; j++)
                {
                    // 每次在大基准图切割一个和匹配小图一样大小的图
                    // 然后和匹配小图进行运算得到一个值
                    // 输出到矩阵的位置

                    // 切割.
                    // 在内循环中，首地址一直向右移动1个单元
                    // 在每一行中，一列一列的循环
                    // 偏移指针, 首地址向右根据当前小矩阵j来移动
                    // 比如 第一个地址为（0,0） 第二个为(0,1)

                    baseL.column = j * offsetValue;  // 每次偏移一个像素位置
                    Matrix baseM = new Matrix(MBig.data, baseL, size);


                    // 比较.
                    double dRtn = CompareMatrix(baseM, MSmall);


                    // 放置值.
                    Mrtn.data[i, j] = dRtn;

                    // 释放资源.
                    baseM.data = null;

                }



            }


            return Mrtn;
        }

        /// <summary>
        /// 比较2个矩阵
        /// </summary>
        /// <param name="baseM"></param>
        /// <param name="MSmall"></param>
        /// <returns></returns>
        private double CompareMatrix(Matrix baseM, Matrix MSmall)
        {
            double dRtn = 0.0;

            double baseMMean = MatrixMean(baseM);
            double smallMean = MatrixMean(MSmall);

            double dSumTop = 0.0;
            double dSumBelow1 = 0.0;
            double dSumBelow2 = 0.0;


            for (int i = 0; i < baseM.Row; i++)
            {
                for (int j = 0; j < baseM.Column; j++)
                {
                    // Top
                    double dTop = (baseM.data[i, j] - baseMMean) * (MSmall.data[i, j] - smallMean);
                    dSumTop = dSumTop + dTop;

                    // Below1
                    double dBelow1 = Math.Pow((baseM.data[i, j] - baseMMean), 2);
                    dSumBelow1 = dSumBelow1 + dBelow1;

                    // Below2
                    double dBelow2 = Math.Pow((MSmall.data[i, j] - smallMean), 2);
                    dSumBelow2 = dSumBelow2 + dBelow2;
                }
            }


            dRtn = dSumTop / Math.Sqrt(dSumBelow1 * dSumBelow2);

            return dRtn;
        }

        /// <summary>
        /// 求矩阵均值
        /// </summary>
        /// <param name="baseM"></param>
        /// <returns></returns>
        private double MatrixMean(Matrix baseM)
        {
            double dRtn = 0.0;

            double dSum = 0.0;

            for (int i = 0; i < baseM.Row; i++)
            {
                for (int j = 0; j < baseM.Column; j++)
                {
                    dSum = dSum + baseM.data[i, j];
                }
            }

            dRtn = dSum / (baseM.Row * baseM.Column);


            return dRtn;
        }

        /// <summary>
        /// 对矩阵元素求绝对值.
        /// </summary>
        /// <param name="A"></param>
        private void ABSMatrix(Matrix A)
        {
            int row = A.Row;
            int column = A.Column;

            for (int i = 0; i < row; i++)
            {
                for (int j = 0; j < column; j++)
                {
                    double dTemp = A.data[i, j];
                    A.data[i, j] = Math.Abs(dTemp);
                }
            }
        }

        private void myMatrixRelease(List<Matrix> Mlist)
        {
            int nNum = Mlist.Count;

            for (int i = 0; i < nNum; i++)
            {
                Mlist[i].data = null;
            }
        }

        /// <summary>
        /// 算法步骤之一
        /// </summary>
        /// <param name="MyBaseM"></param>
        /// <param name="Lvector"></param>
        /// <returns></returns>
        private List<Matrix> GetMatrixList(Matrix[,] MyBaseM, Location[] Lvector)
        {
            // 通道数量
            int nVector = Lvector.Length;

            // 因为是12个通道 所以暂时固定为4
            const int C_Length = 4;

            // 计算针对同一个通道的矩阵 Height和Width
            int iRow = MyBaseM.GetLength(0) - C_Length;
            int iCol = MyBaseM.GetLength(1) - C_Length;

            // 12个46*46矩阵
            List<Matrix> Mlist = new List<Matrix>();

            // 遍历12个通道, 组成为12个 Matrix数组 46*46
            // 3，3起始位置是个很特殊的值
            int baseRow = 2;
            int baseColumn = 2;

            for (int z = 0; z < nVector; z++)
            {
                // 为每一个通道做一层，根据输入矩阵大小 - 一个常量来计算
                Matrix eachM = new Matrix(iRow, iCol);


                // 遍历12个通道时，对46*46 相对于通道的矩阵做处理
                for (int i = 0; i < iRow; i++)
                {
                    for (int j = 0; j < iCol; j++)
                    {
                        // 取得当前row column
                        // 在大矩阵中获得相应矩阵
                        int curRow = i + baseRow;
                        int curCol = j + baseColumn;
                        Matrix curM = MyBaseM[curRow, curCol];

                        // 参考值矩阵
                        Location curL = Lvector[z];
                        int calRow = curRow + curL.row;
                        int calCol = curCol + curL.column;
                        Matrix calM = MyBaseM[calRow, calCol];


                        // 当前矩阵和参考矩阵做运算 得到一个值，放到i,j这个
                        // 位置，
                        double Rtn = Calucate1(curM, calM);
                        eachM.data[i, j] = Rtn;
                    }
                }
                // 加入到一个List里
                Mlist.Add(eachM);
            }

            return Mlist;
        }

        /// <summary>
        /// 求2个矩阵相差的乘方和
        /// </summary>
        /// <param name="curM"></param>
        /// <param name="calM"></param>
        /// <returns></returns>
        private double Calucate1(Matrix curM, Matrix calM)
        {
            double dRtn = 0.0;

            int row = curM.Row;
            int column = curM.Column;
            double sum = 0.0;

            for (int i = 0; i < row; i++)
            {
                for (int j = 0; j < column; j++)
                {
                    double dTemp = curM.data[i, j] - calM.data[i, j];
                    dTemp = Math.Pow(dTemp, 2);

                    sum = sum + dTemp;

                }
            }

            dRtn = 0 - sum;

            return dRtn;
        }

        /// <summary>
        /// 释放内存函数 循环里释放所有占用的内存
        /// </summary>
        /// <param name="MyBaseM"></param>
        private void myMatrixRelease(Matrix[,] MyBaseM)
        {
            int length = MyBaseM.GetLength(0);

            for (int i = 0; i < length; i++)
            {
                for (int j = 0; j < length; j++)
                {
                    MyBaseM[i, j].data = null;
                }
            }
        }

        /// <summary>
        /// 这个空间看看如何分配的
        /// 输入一个大矩阵，返回以8*8基本矩阵为基础的嵌套矩阵
        /// </summary>
        /// <param name="PicBase"></param>
        /// <param name="SmallBaseSize"></param>
        /// <returns></returns>
        private Matrix[,] SplitMatrix(double[,] PicBase, mySize SmallBaseSize)
        {
            Matrix[,] mRtn = null;

            // 判断需要开辟多大的矩阵
            int iBaseSize = SmallBaseSize.ROW;
            int iBigSize = PicBase.GetLength(0);
            int nNeed = iBigSize / iBaseSize;

            mRtn = new Matrix[nNeed, nNeed];

            // 切割矩阵的控制代码，先写死 速度做出来

            Location baseL = new Location(0, 0);
            for (int i = 0; i < nNeed; i++)
            {
                // 在外循环中，首地址一直向下移动8个单元
                // 便利循环下一列
                baseL.row = i * iBaseSize;

                for (int j = 0; j < nNeed; j++)
                {
                    // 在内循环中，首地址一直向右移动8个单元
                    // 在每一行中，一列一列的循环

                    // 偏移指针, 首地址向右根据当前小矩阵j来移动
                    // 比如 第一个地址为（0,0） 第二个为(0,8)
                    baseL.column = j * 8;
                    Matrix eachM = new Matrix(PicBase, baseL, SmallBaseSize);

                    mRtn[i, j] = eachM;
                }
            }

            return mRtn;
        }

        /// <summary>
        /// 把图片里的值 设置到空白的内存里.
        /// </summary>
        /// <param name="strBase">图片来源</param>
        /// <param name="PicBase">写入的内存</param>
        private void SetPicData(string strFile, double[,] PicBase)
        {
            // 用一个Image.
            Image image = Image.FromFile(strFile);

            // 这里会开辟新内存
            Bitmap bitmap = new Bitmap(image);

            // 如果是Tif 没有RGB分量  不用经过灰度图转换
            int width = image.Width;
            int height = image.Height;

            // 放在第一个的也是高度，也就是行数
            // 放在第二个的是宽度，也就是列数
            int[,] I = new int[height, width];
 
            Color c = new Color();
            int[,] r = new int[height, width];//存储整幅图像的红色分量的像素信息
            int[,] g = new int[height, width];//存储整幅图像的绿色分量的像素信息
            int[,] b = new int[height, width];//存储整幅图像的蓝色分量的像素信息

            for (int i = 0; i < height; i++)  //整幅图像行(高)
            {
                for (int j = 0; j < width; j++)//整幅图像列（宽）
                {
                    // GetPixel 函数在读取元素时，行列是反着的
                    c = bitmap.GetPixel(j, i);//获取图片每个点灰度
                    r[i, j] = c.R;
                    g[i, j] = c.G;
                    b[i, j] = c.B;

                    //分离出三个分量的值赋给相应的像素矩阵
                    //获取整个图片的灰度图
                    I[i, j] = Convert.ToInt32(0.2989 * r[i, j] + 0.587 * g[i, j] + 0.114 * b[i, j]);

                }
            }
            // I.GetLength

            ChangetoDouble(I, PicBase);

            // 释放文件.

            I = null;
            r = null;
            g = null;
            b = null;

            bitmap.Dispose();
            image.Dispose();
        }

        /// <summary>
        /// 获得图片的Row和Colomn值
        /// </summary>
        /// <param name="strBase">文件名字</param>
        /// <returns>返回mySize对象</returns>
        private mySize GetPicSize(string strFile)
        {
            mySize sizeRtn = new mySize(0,0);

            // 用一个Image.
            Image image = Image.FromFile(strFile);

            // 这里会开辟新内存
            Bitmap bitmap = new Bitmap(image);

            // 如果是Tif 没有RGB分量  不用经过灰度图转换
            sizeRtn.COL = image.Width;
            sizeRtn.ROW = image.Height;

            // 释放资源
            bitmap.Dispose();
            image.Dispose();

            return sizeRtn;
        }

        /// <summary>
        /// 把Uint8转换为double类型
        /// </summary>
        /// <param name="data"></param>
        /// <param name="setData"></param>
        private void ChangetoDouble(int[,] data, double[,] setData)
        {


            int iRow = data.GetLength(0);       // 行数
            int iColumn = data.GetLength(1);    // 列数

            for (int i = 0; i < iRow; i++)
            {
                for (int j = 0; j < iColumn; j++)
                {
                    double dTemp = 0.0;
                    double Uint8 = 255.0;

                    dTemp = data[i, j] / Uint8;
                    setData[i, j] = Math.Round(dTemp, 5);
                }
            }
        }

        /// <summary>
        /// 辅助函数 想个好的处理方式
        /// </summary>
        /// <returns></returns>
        private Int32 GetTime()
        {
            Int32 nRtn = 0;

            int nHour = System.DateTime.Now.Hour;
            int nMinute = System.DateTime.Now.Minute;
            int nSecond = System.DateTime.Now.Second;
            int nMilliSecond = System.DateTime.Now.Millisecond;

            nRtn = nMilliSecond + nSecond * 1000 + nMinute * 60 * 1000 + nHour * 3600 * 1000;


            return nRtn;
        }

        public void RequestStop()
        {
            _shouldStop = true;
        }
    }
}
